package org.session.util;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

public final class SerializationTools {
    public static String serializeObjectToString(Object toSerialize) {
        if (toSerialize == null) {
            throw new IllegalArgumentException(
                    "How am I suppose to flatten a null object!");
        }
        if (!(toSerialize instanceof Serializable)) {
            throw new IllegalArgumentException(
                    "How am I suppose to flatten a non-serializable object!");
        }
        String serializedString = null;
        ByteArrayOutputStream baos = null;
        ObjectOutputStream oos = null;
        try {
            baos = new ByteArrayOutputStream();
            oos = new ObjectOutputStream(new BufferedOutputStream(baos));
            oos.writeObject(toSerialize);
            oos.flush();
            serializedString = serializeHexBytes(baos.toByteArray());
        } catch (IOException ioException) {
            // TODO: log me
        } finally {
            try {
                if (baos != null) {
                    baos.close();
                }
                if (oos != null) {
                    oos.close();
                }
            } catch (IOException ioException) {
                // TODO: log me
            }
        }

        return serializedString;
    }

    public static Object deserializeObjectFromString(String toDeserialize) {
        Object deserializedObject = null;
        if (!CharacterTools.isNullOrEmpty(toDeserialize)) {
            ObjectInputStream ois = null;
            BufferedInputStream bis = null;
            try {
                bis = new BufferedInputStream(new ByteArrayInputStream(
                        deserializeHexBytes(toDeserialize)));
                ois = new ObjectInputStream(bis);
                deserializedObject = ois.readObject();
            } catch (IOException ioException) {
                // TODO: log me
            } catch (ClassNotFoundException classNotFoundException) {
                // TODO: log me
            } finally {
                try {
                    if (bis != null) {
                        bis.close();
                    }
                    if (ois != null) {
                        ois.close();
                    }
                } catch (IOException ioException) {
                    // TODO: log me
                }
            }
        }

        return deserializedObject;
    }

    public static String serializeHexBytes(byte[] arr) {
        StringBuilder hexString = new StringBuilder(2 * arr.length);
        for (byte b : arr) {
            hexString.append("0123456789ABCDEF".charAt((b & 0xF0) >> 4))
                    .append("0123456789ABCDEF".charAt((b & 0x0F)));
        }

        return hexString.toString();
    }

    public static byte[] deserializeHexBytes(String sbytes) {
        byte[] bytes = new byte[sbytes.length() / 2];
        for (int i = 0, j = 0; i < bytes.length;) {
            char upper = Character.toLowerCase(sbytes.charAt(j++));
            char lower = Character.toLowerCase(sbytes.charAt(j++));
            bytes[i++] = (byte) ((Character.digit(upper, 16) << 4) | Character
                    .digit(lower, 16));
        }

        return bytes;
    }

    private SerializationTools() {
    }
}
